home *** CD-ROM | disk | FTP | other *** search
/ Night Owl 8 / Night Owl CD-ROM (NOPV8) (Night Owl Publisher) (1993).ISO / 017a / binutils.arj / OBJDUMP.C < prev    next >
C/C++ Source or Header  |  1991-03-27  |  8KB  |  364 lines

  1. /* objdump -- dump information about an object file.
  2.    Copyright (C) 1988, Free Software Foundation, Inc.
  3.  
  4.    This program is free software; you can redistribute it and/or modify
  5.    it under the terms of the GNU General Public License as published by
  6.    the Free Software Foundation; either version 1, or (at your option)
  7.    any later version.
  8.  
  9.    This program is distributed in the hope that it will be useful,
  10.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  11.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12.    GNU General Public License for more details.
  13.  
  14.    You should have received a copy of the GNU General Public License
  15.    along with this program; if not, write to the Free Software
  16.    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
  17.  
  18. /*
  19.  * objdump
  20.  * 
  21.  * dump information about an object file.  Until there is other documentation,
  22.  * refer to the manual page dump(1) in the system 5 program's reference manual
  23.  */
  24. #include <stdio.h>
  25. #include "getopt.h"
  26.  
  27. #ifdef GNUDOS
  28. #include <sys/file.h>
  29. #endif
  30.  
  31. #ifndef COFF_ENCAPSULATE
  32. #ifdef GNUDOS
  33. #include <aout.h>
  34. #else
  35. #include <a.out.h>
  36. #endif
  37. /* Tell a.out.gnu.h not to try to redefine some things.  */
  38. #define N_NLIST_DECLARED
  39. #define N_RELOCATION_INFO_DECLARED
  40. #ifndef GNUDOS
  41. #define __STRUCT_EXEC_OVERRIDE__
  42. #define N_MAGIC(exec) ((exec).a_magic)
  43. #endif
  44. #ifdef GNUDOS
  45. #include "aoutgnu.h"
  46. #else
  47. #include "a.out.gnu.h"
  48. #endif
  49. #else
  50. #ifdef GNUDOS
  51. #include "aoutencap.h"
  52. #else
  53. #include "a.out.encap.h"
  54. #endif
  55. #endif
  56.  
  57. #ifndef GNUDOS
  58. char *malloc();
  59. #endif
  60. char *xmalloc();
  61. int nsyms;
  62. struct nlist *symtbl;
  63. char *strtbl;
  64. int strsize;
  65. char *program_name;
  66.  
  67. read_symbols (execp, f)
  68. struct exec *execp;
  69. FILE *f;
  70. {
  71.     int i;
  72.     struct nlist *sp;
  73.     if (symtbl)
  74.         return;
  75.     nsyms = execp->a_syms / sizeof (struct nlist);
  76.     if (nsyms == 0)
  77.         return;
  78.  
  79.     symtbl = (struct nlist *)xmalloc (nsyms * sizeof (struct nlist));
  80.  
  81.     fseek (f, N_STROFF(*execp), 0);
  82.     if (fread ((char *)&strsize, sizeof strsize, 1, f) != 1) {
  83.         fprintf (stderr, "%s: can not read string table size\n",
  84.              program_name);
  85.         exit (1);
  86.     }
  87.     strtbl = xmalloc (strsize);
  88.     fseek (f, N_STROFF (*execp), 0);
  89.     if (fread (strtbl, 1, strsize, f) != strsize) {
  90.         fprintf (stderr, "%s: error reading string table\n",
  91.              program_name);
  92.         exit (1);
  93.     }
  94.  
  95.     fseek (f, N_SYMOFF (*execp), 0);
  96.     if (fread ((char *)symtbl, sizeof (struct nlist), nsyms, f) != nsyms) {
  97.         fprintf (stderr, "%s: error reading symbol table\n",
  98.              program_name);
  99.         exit (1);
  100.     }
  101.  
  102.     for (i = 0, sp = symtbl; i < nsyms; i++, sp++) {
  103.         if (sp->n_un.n_strx == 0)
  104.             sp->n_un.n_name = "";
  105.         else if (sp->n_un.n_strx < 0 || sp->n_un.n_strx > strsize)
  106.             sp->n_un.n_name = "<bad string table index>";
  107.         else
  108.             sp->n_un.n_name = strtbl + sp->n_un.n_strx;
  109.     }
  110. }
  111.  
  112. free_symbols ()
  113. {
  114.     if (symtbl)
  115.         free (symtbl);
  116.     symtbl = NULL;
  117.     if (strtbl)
  118.         free (strtbl);
  119.     strtbl = NULL;
  120. }
  121.  
  122.  
  123. usage ()
  124. {
  125.     fprintf (stderr, "\
  126. Usage: %s [-hnrt] [+header] [+nstuff] [+reloc] [+symbols] file...\n",
  127.          program_name);
  128.     exit (1);
  129. }
  130.  
  131. int hflag;
  132. int nflag;
  133. int rflag;
  134. int tflag;
  135.  
  136. /* Size of a page.  Required by N_DATADDR in a.out.gnu.h [VAX].  */
  137. int page_size;
  138.  
  139. main (argc, argv)
  140. char **argv;
  141. {
  142.     int c;
  143.     extern char *optarg;
  144.     extern int optind;
  145.     int seenflag = 0;
  146.     int ind = 0;
  147.     static struct option long_options[] = 
  148.       {
  149.         {"symbols",   0, &tflag, 1},
  150.         {"reloc",  0, &rflag, 1},
  151.         {"nstuff", 0, &nflag, 1},
  152.         {"header", 0, &hflag, 1},
  153.         {NULL, 0, NULL, 0}
  154.       };
  155.  
  156. #ifdef GNUDOS
  157.     _fmode = O_BINARY; /* set default file type */
  158. #endif
  159.  
  160.     page_size = getpagesize ();
  161.  
  162.     program_name = argv[0];
  163.                   
  164.     while ((c = getopt_long (argc, argv, "hnrt", long_options, &ind))
  165.                != EOF) {
  166.         seenflag = 1;
  167.         switch (c) {
  168.         case  0 : break; /* we've been given a long option */
  169.         case 't': tflag = 1; break;
  170.         case 'r': rflag = 1; break;
  171.         case 'n': nflag = 1; break;
  172.         case 'h': hflag = 1; break;
  173.         default:
  174.             usage ();
  175.         }
  176.     }
  177.  
  178.     if (seenflag == 0 || optind == argc)
  179.         usage ();
  180.  
  181.     while (optind < argc)
  182.         doit (argv[optind++]);
  183. }
  184.  
  185. doit (name)
  186. char *name;
  187. {
  188.     FILE *f;
  189.     struct exec exec;
  190.     printf ("%s:\n", name);
  191.     f = fopen (name, "r");
  192.     if (f == NULL) {
  193.         fprintf (stderr, "%s: can not open ", program_name);
  194.         perror (name);
  195.         return;
  196.     }
  197. #ifdef HEADER_SEEK
  198.     HEADER_SEEK (f);
  199. #endif
  200.     if (fread ((char *)&exec, sizeof exec, 1, f) != 1) {
  201.         fprintf (stderr, "%s: can not read header for %s\n",
  202.              program_name, name);
  203.         return;
  204.     }
  205.  
  206.     if (N_BADMAG (exec)) {
  207.         fprintf (stderr, "%s: %s is not an object file\n",
  208.              program_name, name);
  209.         return;
  210.     }
  211.  
  212.     if (hflag)
  213.         dump_header (&exec);
  214.  
  215.     if (nflag)
  216.         dump_nstuff (&exec);
  217.  
  218.     if (tflag)
  219.         dump_sym (&exec, f);
  220.  
  221.     if (rflag)
  222.         dump_reloc (&exec, f);
  223.  
  224.     free_symbols ();
  225.  
  226. }
  227.  
  228. dump_header (execp)
  229. struct exec *execp;
  230. {
  231.     int x;
  232.  
  233. #if defined (__GNU_EXEC_MACROS__) && !defined (__STRUCT_EXEC_OVERRIDE__)
  234.     printf ("magic: 0x%x (%o)", N_MAGIC(*execp), N_MAGIC(*execp));
  235.     printf ("machine type: %d", N_MACHTYPE(*execp));
  236.     printf ("flags: 0x%x", N_FLAGS(*execp));
  237. #else /* non-gnu struct exec.  */
  238.     printf ("magic: 0x%x (%o) ", execp->a_magic, execp->a_magic);
  239. #endif /* non-gnu struct exec.  */
  240.     printf ("text 0x%x ", execp->a_text);
  241.     printf ("data 0x%x ", execp->a_data);
  242.     printf ("bss 0x%x\n", execp->a_bss);
  243.     printf ("nsyms %d", execp->a_syms / sizeof (struct nlist));
  244.     x = execp->a_syms % sizeof (struct nlist);
  245.     if (x) 
  246.         printf (" (+ %d bytes)", x);
  247.     printf (" entry 0x%x ", execp->a_entry);
  248.     printf ("trsize 0x%x ", execp->a_trsize);
  249.     printf ("drsize 0x%x\n", execp->a_drsize);
  250. }
  251.  
  252. dump_nstuff (execp)
  253. struct exec *execp;
  254. {
  255.     printf ("N_BADMAG %d\n", N_BADMAG (*execp));
  256.     printf ("N_TXTOFF 0x%x\n", N_TXTOFF (*execp));
  257.     printf ("N_SYMOFF 0x%x\n", N_SYMOFF (*execp));
  258.     printf ("N_STROFF 0x%x\n", N_STROFF (*execp));
  259.     printf ("N_TXTADDR 0x%x\n", N_TXTADDR (*execp));
  260.     printf ("N_DATADDR 0x%x\n", N_DATADDR (*execp));
  261. }
  262.  
  263. dump_sym (execp, f)
  264. struct exec *execp;
  265. FILE *f;
  266. {
  267.     int i;
  268.     struct nlist *sp;
  269.  
  270.     read_symbols (execp, f);
  271.     if (nsyms == 0) {
  272.         printf ("no symbols\n");
  273.         return;
  274.     }
  275.  
  276.     printf ("%3s: %4s %5s %4s %8s\n",
  277.         "#", "type", "other", "desc", "val");
  278.     for (i = 0, sp = symtbl; i < nsyms; i++, sp++) {
  279.         printf ("%3d: %4x %5x %4x %8x %s\n",
  280.             i,
  281.             sp->n_type & 0xff,
  282.             sp->n_other & 0xff,
  283.             sp->n_desc & 0xffff,
  284.             sp->n_value,
  285.             sp->n_un.n_name);
  286.     }
  287. }
  288.  
  289. dump_reloc (execp, f)
  290. struct exec *execp;
  291. FILE *f;
  292. {
  293.     read_symbols (execp, f);
  294.     if (execp->a_trsize) {
  295.         printf ("text reloc\n");
  296.         dump_reloc1 (execp, f, N_TRELOFF (*execp), execp->a_trsize);
  297.     }
  298.     if (execp->a_drsize) {
  299.         printf ("data reloc\n");
  300.         dump_reloc1 (execp, f, N_DRELOFF (*execp), execp->a_drsize);
  301.     }
  302. }
  303.  
  304. dump_reloc1 (execp, f, off, size)
  305. struct exec *execp;
  306. FILE *f;
  307. {
  308.     int nreloc;
  309.     struct relocation_info reloc;
  310.     int i;
  311.  
  312.     nreloc = size / sizeof (struct relocation_info);
  313.  
  314.     printf ("%3s: %3s %8s %4s\n", "#", "len", "adr", "sym");
  315.     fseek (f, off, 0);
  316.     for (i = 0; i < nreloc; i++) {
  317.         if (fread ((char *)&reloc, sizeof reloc, 1, f) != 1) {
  318.             fprintf (stderr, "%s: error reading reloc\n",
  319.                  program_name);
  320.             return;
  321.         }
  322.         printf ("%3d: %3d %8x ", i, 1 << reloc.r_length,
  323.             reloc.r_address);
  324.         
  325.         if (reloc.r_extern) {
  326.             printf ("%4d ", reloc.r_symbolnum);
  327.             if (reloc.r_symbolnum < nsyms)
  328.                 printf ("%s ",
  329.                     symtbl[reloc.r_symbolnum].n_un.n_name);
  330.         } else {
  331.             printf ("     ");
  332.             switch (reloc.r_symbolnum & ~N_EXT) {
  333.             case N_TEXT: printf (".text "); break;
  334.             case N_DATA: printf (".data "); break;
  335.             case N_BSS: printf (".bss "); break;
  336.             case N_ABS: printf (".abs "); break;
  337.             default: printf ("base %x ", reloc.r_symbolnum); break;
  338.             }
  339.         }
  340.         if (reloc.r_pcrel) printf ("PCREL ");
  341. #if 0
  342.         if (reloc.r_pad) printf ("PAD %x ", reloc.r_pad);
  343. #endif
  344.         printf ("\n");
  345.     }
  346. }
  347.  
  348. /* Allocate `n' bytes of memory dynamically, with error checking.  */
  349.  
  350. char *
  351. xmalloc (n)
  352.      unsigned n;
  353. {
  354.   char *p;
  355.  
  356.   p = malloc (n);
  357.   if (p == 0)
  358.     {
  359.       fprintf (stderr, "%s: virtual memory exhausted\n", program_name);
  360.       exit (1);
  361.     }
  362.   return p;
  363. }
  364.